// Copyright 2019 by 马万里. All rights reserved.
// 开发团队 ：   鸡中之霸
// 开发人员 ：   马万里
// 开发时间 ：   2019-03-06 19:25
// 文件名称 ：   des_cbc.go
// 工程名称 ：   goCryptor
// 开发工具 ：   GoLand
//

package des

import (
	"bytes"
	"crypto/cipher"
	"crypto/des"
	"errors"
	"fmt"
)

func EnCriptDESOFB(key, iv, src []byte) ([]byte, error) {

	// 1. 获取aes的block接口
	block, e := des.NewCipher(key)
	if e != nil {
		return nil, e
	}
	if len(iv) != block.BlockSize() {
		return nil, errors.New(fmt.Sprintf("iv长度应该为%d个字节\n", block.BlockSize()))
	}

	// 2. CBC补位
	src = addPadding(src, block.BlockSize())

	// 3. 获取blockMode接口
	blockModel := cipher.NewCBCEncrypter(block, iv)

	// 4. 加密
	blockModel.CryptBlocks(src, src)
	return src, nil
}

func addPadding(src []byte, blockSize int) []byte {

	length := len(src)

	remains := length % blockSize
	paddingNum := blockSize - remains

	padding := bytes.Repeat([]byte{byte(paddingNum)}, paddingNum)

	src = append(src, padding...)

	return src
}

// 	根据传入的key,iv以及需要解密的字符切片,获取aes-cbc解密后的字符切片.
//
// 	key:
// 	- 16位字符	:	aes-128
// 	- 24位字符	:	aes-192
// 	- 32位字符	:	aes-256
// 	iv:
// 	- 16位字符.
// 	src:
//	- 传入的值.
//	dst:
//	- 加密后切片.
//	err:
//	- 错误.
func DeCryptAESCBC(key, iv, src []byte) ([]byte, error) {

	// 1. 获取aes的block接口
	block, e := des.NewCipher(key)
	if e != nil {
		return nil, e
	}
	if len(iv) != block.BlockSize() {
		return nil, errors.New(fmt.Sprintf("iv长度应该为%d个字节\n", block.BlockSize()))
	}

	// 2. 获取blockMode接口
	decrypter := cipher.NewCBCDecrypter(block, iv)

	// 3. 解密
	decrypter.CryptBlocks(src, src)

	// 4. 去除padding
	src = removePadding(src)

	return src, nil
}

// 删除padding
func removePadding(src []byte) []byte {

	// 1. 获取length
	length := len(src)

	// 2. 获取最后一个表示padding长度的数字
	paddingNum := int(src[length-1])

	// 3. 去除padding
	src = src[:length-paddingNum]

	return src
}
